/*===========================================================================
  Copyright (C) 2014 by the Okapi Framework contributors
-----------------------------------------------------------------------------
  This library is free software; you can redistribute it and/or modify it 
  under the terms of the GNU Lesser General Public License as published by 
  the Free Software Foundation; either version 2.1 of the License, or (at 
  your option) any later version.

  This library is distributed in the hope that it will be useful, but 
  WITHOUT ANY WARRANTY; without even the implied warranty of 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 
  General Public License for more details.

  You should have received a copy of the GNU Lesser General Public License 
  along with this library; if not, write to the Free Software Foundation, 
  Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

  See also the full LGPL text here: http://www.gnu.org/copyleft/lesser.html
===========================================================================*/

package net.sf.okapi.v2.common.om.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import net.sf.okapi.v2.common.LocaleId;
import net.sf.okapi.v2.common.om.ISegment;
import net.sf.okapi.v2.common.om.IStore;
import net.sf.okapi.v2.common.om.ITags;
import net.sf.okapi.v2.common.om.ITextContainer;
import net.sf.okapi.v2.common.om.ITextFragment;

/**
 * Implements {@link ITextContainer}.
 */
public class TextContainer implements ITextContainer {

	private ITags tags;
	private List<ITextFragment> parts;
	
	/**
	 * Creates a new {@link ITextContainer} object associated with a given {@link IStore}.
	 * @param store the store to associate with this new container.
	 * @param locId the locale for the new container (use null for source).
	 */
	public TextContainer (IStore store,
		LocaleId locId)
	{
		tags = new Tags(store);
		store.register(this, locId);
		parts = new ArrayList<>(2);
		parts.add(new Segment(this));
	}

	/**
	 * Copy constructor.
	 * @param origin the original container to copy.
	 * @param store the store to associate with this new container.
	 * @param locId the locale for the new container (use null for source).
	 */
	public TextContainer (ITextContainer origin,
		IStore store,
		LocaleId locId)
	{
		tags = new Tags(store);
		store.register(this, locId);
		parts = new ArrayList<>(origin.size());
		// Clone the parts
		for ( ITextFragment oriPart : origin ) {
			parts.add(new TextFragment(this, oriPart));
		}
	}
	
	@Override
	public ITags getTags () {
		return tags;
	}
	
	@Override
	public String getText () {
		StringBuilder tmp = new StringBuilder();
		for ( ITextFragment part : parts ) {
			tmp.append(part.getText());
		}
		return tmp.toString();
	}

	@Override
	public Iterator<ITextFragment> iterator () {
		return parts.iterator();
	}

	@Override
	public boolean isEmpty () {
		for ( ITextFragment part : parts ) {
			if ( !part.isEmpty() ) return false;
		}
		return true;
	}

	@Override
	public int size () {
		return parts.size();
	}

	@Override
	public ISegment appendSegment () {
		return appendSegment(true);
	}

	@Override
	public ISegment appendSegment (boolean usePreviousIfEmpty) {
		if ( usePreviousIfEmpty ) {
			ITextFragment tf = parts.get(parts.size()-1);
			if ( tf.isSegment() && tf.isEmpty() ) {
				return (ISegment)tf;
			}
		}
		// All other cases: create a new segment
		ISegment seg = new Segment(this);
		parts.add(seg);
		return seg;
	}

	@Override
	public ITextFragment getPart (int partIndex) {
		return parts.get(partIndex);
	}

	@Override
	public ITextFragment getPart (String id) {
		for ( ITextFragment part : parts ) {
			if ( id.equals(part.getId()) ) {
				return part;
			}
		}
		return null;
	}

	@Override
	public ISegment getSegment (int segIndex) {
		int si = 0;
		for ( int i=0; i<parts.size(); i++ ) {
			if ( parts.get(i).isSegment() ) {
				if ( si == segIndex ) {
					return (ISegment)parts.get(i);
				}
				si++;
			}
		}
		throw new IndexOutOfBoundsException(
			String.format("The index %d is out-of-bound for segments.", segIndex));
	}

	@Override
	public ISegment getSegment (String id) {
		for ( ITextFragment part : parts ) {
			if ( part.isSegment() && id.equals(part.getId()) ) {
				return (ISegment)part;
			}
		}
		return null;
	}


}
